package com.cxh.rmsq.utils

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Matrix
import android.media.MediaMetadataRetriever
import android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT
import android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION
import android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import coil.request.Disposable
import com.alipay.sdk.app.PayTask
import com.amap.api.maps.model.LatLng
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.cxh.rmsq.R
import com.cxh.rmsq.db.model.PayOrderBean
import com.cxh.rmsq.wx.WxPayBean
import com.google.gson.Gson
import com.maning.mndialoglibrary.MProgressDialog
import com.nostra13.universalimageloader.core.ImageLoader
import com.tencent.mm.opensdk.modelpay.PayReq
import com.tencent.mm.opensdk.openapi.IWXAPI
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.logging.HttpLoggingInterceptor
import java.io.File
import java.io.IOException
import java.math.RoundingMode
import java.net.Inet4Address
import java.net.NetworkInterface
import java.net.URISyntaxException
import java.text.DecimalFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Matcher
import java.util.regex.Pattern


fun loge(msg: String) {
    Log.e("TAG1111", msg)
}


fun toJson(any: Any): String = Gson().toJson(any)

@SuppressLint("SimpleDateFormat")
fun getDate(): String {
    val date = Date(System.currentTimeMillis())
    val formatter = SimpleDateFormat("yyyy-MM-dd")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getDate(date: Date): String {
    val formatter = SimpleDateFormat("yyyy-MM")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getDateOfSecond(date: Date): String {
    val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getDateOfMinute(date: Date): String {
    val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getDateOfDay(date: Date): String {
    val formatter = SimpleDateFormat("yyyy-MM-dd")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun formatDayTime(date: Date): String {
    val formatter = SimpleDateFormat("MM-dd HH:mm")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getFormatDate(date: Date?): String {
    date?.let {
        val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm")
        val calendar = Calendar.getInstance()
        calendar.time = date
        val index = calendar.get(Calendar.DAY_OF_WEEK) - 1
        val week = when (index) {
            1 -> "(周一)"
            2 -> "(周二)"
            3 -> "(周三)"
            4 -> "(周四)"
            5 -> "(周五)"
            6 -> "(周六)"
            else -> "(周日)"
        }
        val split = formatter.format(date).split(" ")
        return "${split[0]} $week ${split[1]}"
    } ?: return ""
}

@SuppressLint("SimpleDateFormat")
fun getDateOfYear(date: Date): String {
    val formatter = SimpleDateFormat("yyyy")
    return formatter.format(date)
}

@SuppressLint("SimpleDateFormat")
fun getDateToMonth(date: Date): String {
    val formatter = SimpleDateFormat("yyyy-MM")
    return formatter.format(date)
}


@SuppressLint("SimpleDateFormat")
fun getTime(): String {
    val date = Date(System.currentTimeMillis())
    val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    return formatter.format(date)
}

/**
 * 倒计时HH:mm:ss
 */
@SuppressLint("SimpleDateFormat")
fun getTimer(currentTime: Int): String {
    val date = Date((currentTime * 1000).toLong())
    val formatter = SimpleDateFormat("HH:mm:ss")
    formatter.timeZone = TimeZone.getTimeZone("GMT+00:00")
    return formatter.format(date)
}

/**
 * 获取一个日期距今天的倒计时
 */
@SuppressLint("SimpleDateFormat")
fun getTheRemainingTime(date: String): Int {
    val formatter = SimpleDateFormat("yyyy-MM-dd")
    val date = formatter.parse(date)
    return ((date.time - System.currentTimeMillis()) / 1000).toInt()
}

@SuppressLint("SimpleDateFormat")
fun getArrayTime(currentTime: Int): List<String> {
    val date = Date((currentTime * 1000).toLong())
    val formatter = SimpleDateFormat("HH:mm:ss")
    formatter.timeZone = TimeZone.getTimeZone("GMT+00:00")
    return formatter.format(date).split(":")
}

/**
 * 比较两个日期相差多少天
 */
//fun compareTime(date: String): Int {
//    val pre = Calendar.getInstance()
//    val predate = Date(System.currentTimeMillis())
//    pre.time = predate
//
//    val cal = Calendar.getInstance()
//    val date = DayUtils.getDateFormat().parse(date)
//    cal.time = date
//
//    if (cal[Calendar.YEAR] == pre[Calendar.YEAR]) {
//
//        return (cal[Calendar.DAY_OF_YEAR]
//                - pre[Calendar.DAY_OF_YEAR])
//    }
//    return -1
//}

@SuppressLint("SimpleDateFormat")
fun getTimeMinute(): String {
    val date = Date(System.currentTimeMillis())
    val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm")
    return formatter.format(date)
}

fun loadImage(url: Any?, view: ImageView) {
    val options = RequestOptions().centerCrop().placeholder(R.mipmap.image_zanwei)
        .error(R.mipmap.image_zanwei)
    Glide.with(view.context).load(url).apply(options).into(view)
}

fun loadImage(url: Any?, defaultImage: Int, view: ImageView) {
    val options = RequestOptions().centerCrop().placeholder(defaultImage).error(defaultImage)
    Glide.with(view.context).load(url).apply(options).into(view)
}

class BannerGlideImageLoader : ImageLoader() {
    fun displayImage(context: Context?, path: Any, imageView: ImageView) {
        loadImage(path, imageView)
    }

}

private fun buildTransaction(type: String): String {
    return type + System.currentTimeMillis()
}

//fun wechatPay(iwxapi: IWXAPI, data: WxConfig) {
//    val payReq = PayReq()
//    payReq.appId = data.appId
//    payReq.partnerId = data.partnerId
//    payReq.prepayId = data.prepayId
//    payReq.nonceStr = data.nonceStr
//    payReq.timeStamp = data.timeStamp
//    payReq.packageValue = data.packageStr
//    payReq.sign = data.sign
//    iwxapi.sendReq(payReq)
//}
//
fun wechatPay(iwxapi: IWXAPI, data: WxPayBean) {
    val payReq = PayReq()
    payReq.appId = data.appid
    payReq.partnerId = data.partnerId
    payReq.prepayId = data.prepayId
    payReq.nonceStr = data.noncestr
    payReq.timeStamp = data.timestamp
    payReq.packageValue = data.packageValue
    payReq.sign = data.sign
    Log.e("拉起参数", Gson().toJson(payReq))
    iwxapi.sendReq(payReq)
}
/*fun Activity.aliPay(it: String): Disposable {
    return Observable.create { emitter: ObservableEmitter<Boolean> ->
        val alipay = PayTask(this)
        val result = alipay.payV2(it, true)

        val payResult = PayResult(result)

*//**
 * 对于支付结果，请商户依赖服务端的异步通知结果。同步通知结果，仅作为支付结束的通知。
 *//*

        val resultInfo = payResult.getResult()// 同步返回需要验证的信息
        val resultStatus = payResult.getResultStatus()
        loge("支付宝支付: $resultInfo, $resultStatus")
        // 判断resultStatus 为9000则代表支付成功
        if (TextUtils.equals(resultStatus, "9000")) {
            // 该笔订单是否真实支付成功，需要依赖服务端的异步通知。
            emitter.onNext(true)
        } else {
            // 该笔订单真实的支付结果，需要依赖服务端的异步通知。
            emitter.onNext(false)
        }
    }.subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({ isPaySuccess ->
            if (isPaySuccess) {
//                EventBus.getDefault()
//                    .post(EventMessage(EventMessage.EventState.ALI_PAY_SUCCESS, ""))
//            } else {
//                EventBus.getDefault().post(EventMessage(EventMessage.EventState.ALI_PAY_ERROR, ""))
            }
        }, {})
}*/

fun Context.callPhone(phone: String) {
    Log.e("1111111111111111", "callPhone: " + phone)

    val intent = Intent(Intent.ACTION_DIAL)
    // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    intent.data = Uri.parse("tel:$phone")
    startActivity(intent)
}

fun doubleScale2(value: Double) = value.toBigDecimal().setScale(2, RoundingMode.HALF_UP).toDouble()

/**
 * 验证手机格式
 */
fun isMobileNO(mobiles: String): Boolean {
    val telRegex =
        "[1][356789]\\d{9}"//"[1]"代表第1位为数字1，"[358]"代表第二位可以为3、5、8中的一个，"\\d{9}"代表后面是可以是0～9的数字，有9位。

    return if (TextUtils.isEmpty(mobiles))
        false
    else
        mobiles.matches(telRegex.toRegex())
}

/**
 *
 * 方法描述 隐藏手机号中间位置字符，显示前三后四个字符
 */
fun hidePhoneNo(phoneNo: String): String {
    val length = phoneNo.length
    val beforeLength = 3
    val afterLength = 4
    //替换字符串，当前使用“*”
    val replaceSymbol = "*"
    val sb = StringBuffer()
    for (i in 0 until length) {
        if (i < beforeLength || i >= length - afterLength) {
            sb.append(phoneNo[i])
        } else {
            sb.append(replaceSymbol)
        }
    }
    return sb.toString()
}


//fun isEventRegistered(any: Any) = EventBus.getDefault().isRegistered(any)

/**
 * @param saveDir
 * @return 下载路径
 * @throws IOException 判断下载目录是否存在
 */
@Throws(IOException::class)
fun getDownloadDirPath(): String {
    // 下载位置
    val downloadFile = File(Environment.getExternalStorageDirectory(), "qbs")
    if (!downloadFile.mkdirs()) {
        downloadFile.createNewFile()
    }
    return downloadFile.absolutePath
}

fun byteToMB(size: Long): String {
    val kb: Long = 1024
    val mb = kb * 1024
    val gb = mb * 1024
    if (size >= gb) {
        return String.format("%.1f GB", size.toFloat() / gb)
    } else if (size >= mb) {
        val f = size.toFloat() / mb
        return String.format(if (f > 100) "%.0f MB" else "%.1f MB", f)
    } else if (size > kb) {
        val f = size.toFloat() / kb
        return String.format(if (f > 100) "%.0f KB" else "%.1f KB", f)
    } else {
        return String.format("%d B", size)
    }
}

fun Activity.closeSoftKeyInput() {
    this.currentFocus?.let {
        val imm = getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(
            this.currentFocus!!.windowToken,
            InputMethodManager.HIDE_NOT_ALWAYS
        )
    }

}


fun Activity.showSoftKeyInput(editText: EditText) {
    this.currentFocus?.let {
        val imm = getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(editText, 0)
    }

}

fun Activity.toggleSoftInput() {
    val imm = getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
}

fun Activity.hideSoft(view: View) {
    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?

//    imm!!.showSoftInput(view, InputMethodManager.SHOW_FORCED)

    imm!!.hideSoftInputFromWindow(view.windowToken, 0) //强制隐藏键盘

}

fun Fragment.hideSoft(view: View) {
    val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?

//    imm!!.showSoftInput(view, InputMethodManager.SHOW_FORCED)

    imm!!.hideSoftInputFromWindow(view.windowToken, 0) //强制隐藏键盘

}

fun Fragment.toggleSoftInput() {
    val imm =
        activity!!.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
}

fun Fragment.closeSoftKeyInput() {
    activity!!.currentFocus?.let {
        val imm =
            activity!!.getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(
            activity!!.currentFocus!!.windowToken,
            InputMethodManager.HIDE_NOT_ALWAYS
        )
    }
}

fun subZeroAndDot(s: String): String {
    var s = s
    if (s.indexOf(".") > 0) {
        s = s.replace("0+?$".toRegex(), "")//去掉多余的0
        s = s.replace("[.]$".toRegex(), "")//如最后一位是.则去掉
    }
    return s
}

fun <T> getEmptyList(): List<T> = mutableListOf()

val x_pi = 3.1415926535897932384626

/**
 * GCJ-02 坐标转换成 BD-09 坐标
 */
fun toBD09(gg: LatLng): LatLng {
    val x = gg.longitude
    val y = gg.latitude
    val z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi)
    val theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi)
    val ret = DoubleArray(2)
    ret[1] = z * Math.cos(theta) + 0.0065
    ret[0] = z * Math.sin(theta) + 0.006
    return LatLng(ret[0], ret[1])
}

/**
 * BD-09 转 GCJ-02
 */
fun fromBD09(bd: LatLng): LatLng {
    val x = bd.longitude - 0.0065
    val y = bd.latitude - 0.006
    val z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi)
    val theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi)

    val ret = DoubleArray(2)
    ret[1] = z * Math.cos(theta)
    ret[0] = z * Math.sin(theta)
    return LatLng(ret[0], ret[1])
}

fun Activity.startBaiduMapNavi(endPoint_: LatLng, endName: String) {
    try {
        val endPoint = toBD09(endPoint_)
        val endLag = endPoint.latitude.toString() + "," + endPoint.longitude


        //   Intent intent = Intent.getIntent("intent://map/direction?origin=latlng:" + startLag + "|name:" + startName + "&destination=latlng:" + endLag + "|name:" + endName + "&mode=transit&src=某某公司#Intent;" + "scheme=bdapp;package=com.baidu.BaiduMap;end");
        //起点  此处不传值默认选择当前位置
        val intent =
            Intent.getIntent("intent://map/direction?destination=latlng:$endLag|name:$endName&mode=driving&src=某某公司#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end")


        //            URL接口：baidumap://map/direction
        //            destination : 终点名称或经纬度
        //            经纬度和名称:
        //            latlng:39.9761,116.3282|name:中关村 (注意：坐标先纬度，后经度)
        //            mode : 导航模式 //driving 驾车
        startActivity(intent)

    } catch (e: URISyntaxException) {
        e.printStackTrace()
        Toast.makeText(applicationContext, "地址解析错误", Toast.LENGTH_SHORT).show()
    } catch (e: ActivityNotFoundException) {
        e.printStackTrace()
        Toast.makeText(applicationContext, "您尚未安装百度地图app或app版本过低", Toast.LENGTH_SHORT)
            .show()
    }

}

fun Activity.startBaiduMapNavi(
    starPoint_: LatLng,
    endPoint_: LatLng,
    startName: String,
    endName: String
) {
    try {
        val starPoint = toBD09(starPoint_)
        val startLag = starPoint.latitude.toString() + "," + starPoint.longitude
        val endPoint = toBD09(endPoint_)
        val endLag = endPoint.latitude.toString() + "," + endPoint.longitude


        val intent =
            Intent.getIntent("intent://map/direction?origin=latlng:" + startLag + "|name:" + startName + "&destination=latlng:" + endLag + "|name:" + endName + "&mode=transit&src=某某公司#Intent;" + "scheme=bdapp;package=com.baidu.BaiduMap;end");
//        起点  此处不传值默认选择当前位置
//        val intent =
//                Intent.getIntent("intent://map/direction?destination=latlng:$endLag|name:$endName&mode=driving&src=某某公司#Intent;scheme=bdapp;package=com.baidu.BaiduMap;end")


        //            URL接口：baidumap://map/direction
        //            destination : 终点名称或经纬度
        //            经纬度和名称:
        //            latlng:39.9761,116.3282|name:中关村 (注意：坐标先纬度，后经度)
        //            mode : 导航模式 //driving 驾车
        startActivity(intent)

    } catch (e: URISyntaxException) {
        e.printStackTrace()
        Toast.makeText(applicationContext, "地址解析错误", Toast.LENGTH_SHORT).show()
    } catch (e: ActivityNotFoundException) {
        e.printStackTrace()
        Toast.makeText(applicationContext, "您尚未安装百度地图app或app版本过低", Toast.LENGTH_SHORT)
            .show()
    }

}

fun Activity.startGaoDeNavi(endPoint: LatLng, endName: String) {
    var endPoint = endPoint
    if (!isInstalled("com.autonavi.minimap")) {
        Toast.makeText(this, "请先下载安装高德地图客户端", Toast.LENGTH_SHORT).show()
        return
    }

    val stringBuffer = StringBuffer("androidamap://route?sourceApplication=").append("amap")

    stringBuffer.append("&dlat=").append(endPoint.latitude) //终点纬度
        .append("&dlon=").append(endPoint.longitude) //终点经度
        .append("&dname=").append(endName) //终点地址
        .append("&dev=").append(0)  //起终点是否偏移(0:lat 和 lon 是已经加密后的,不需要国测加密; 1:需要国测加密)
        .append("&t=").append(0)  //t = 0（驾车）= 1（公交）= 2（步行）= 3（骑行）= 4（火车）= 5（长途客车）

    val intent =
        Intent("android.intent.action.VIEW", android.net.Uri.parse(stringBuffer.toString()))
    intent.setPackage("com.autonavi.minimap")
    startActivity(intent)
}

fun Activity.startGaoDeNavi(
    startPoint: LatLng,
    endPoint: LatLng,
    startName: String,
    endName: String
) {
    var endPoint = endPoint
    if (!isInstalled("com.autonavi.minimap")) {
        Toast.makeText(this, "请先下载安装高德地图客户端", Toast.LENGTH_SHORT).show()
        return
    }

    val stringBuffer = StringBuffer("androidamap://route?sourceApplication=").append("amap")

    stringBuffer
        .append("&slat=").append(startPoint.latitude) //起点纬度
        .append("&slon=").append(startPoint.longitude) //起点经度
        .append("&dlat=").append(endPoint.latitude) //终点纬度
        .append("&dlon=").append(endPoint.longitude) //终点经度
        .append("&sname=").append(startName) //终点地址
        .append("&dname=").append(endName) //终点地址
        .append("&dev=").append(0)  //起终点是否偏移(0:lat 和 lon 是已经加密后的,不需要国测加密; 1:需要国测加密)
        .append("&t=").append(0)  //t = 0（驾车）= 1（公交）= 2（步行）= 3（骑行）= 4（火车）= 5（长途客车）

    val intent =
        Intent("android.intent.action.VIEW", android.net.Uri.parse(stringBuffer.toString()))
    intent.setPackage("com.autonavi.minimap")
    startActivity(intent)
}

fun Context.isInstalled(packageName: String): Boolean {
    val packageManager = packageManager//获取packagemanager
    val pinfo = packageManager.getInstalledPackages(0)//获取所有已安装程序的包信息
    if (pinfo != null) {
        for (info in pinfo) {
            if (info.packageName == packageName) {
                return true
            }
            //pName.add(pn);
        }
    }
    return false
}

//fun Context.shareWxMessage(
//    iwxapi: IWXAPI,
//    title: String,
//    description: String,
//    imgUrl: Any,
//    webpageUrl: String,
//    shareType: Int
//) {
//    val webPage = WXWebpageObject()
//    webPage.webpageUrl = webpageUrl
//    val options = RequestOptions().fitCenter()
//
//    Glide.with(this)
//        .asBitmap()
//        .load(imgUrl)
//        .apply(options)
//        .into(object : SimpleTarget<Bitmap>() {
//            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
//                val bitmap = Bitmap.createScaledBitmap(resource, 120, 120, true)
//                val msg = WXMediaMessage(webPage)
//                msg.title = title
//                msg.description = description
////                msg.thumbData = WxUtil.bmpToByteArray(bitmap, true)
//
//                val req = SendMessageToWX.Req()
//                req.transaction = buildTransaction("webpage")
//                req.message = msg
//                req.scene = shareType
//
//                iwxapi.sendReq(req)
//            }
//
//            override fun onLoadFailed(errorDrawable: Drawable?) {
//
//            }
//
//        })
//
//}

//fun postEvent(state: EventMessage.EventState, any: Any) {
//    EventBus.getDefault().post(EventMessage(state, any))
//}

//dip和px转换
fun Context.dip2px(dpValue: Float): Int {
    val scale = resources.displayMetrics.density
    return (dpValue * scale + 0.5f).toInt()
}

//fun getDateFormatGson() = GsonBuilder()
//    .registerTypeAdapter(Date::class.java, DateDeserializer())
//    .create()

fun isIDNumber(IDNumber: String?): Boolean {
    if (IDNumber == null || "" == IDNumber) {
        return false
    }
    // 定义判别用户身份证号的正则表达式（15位或者18位，最后一位可以为字母）
    val regularExpression =
        "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" + "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)"
    //假设18位身份证号码:41000119910101123X  410001 19910101 123X
    //^开头
    //[1-9] 第一位1-9中的一个      4
    //\\d{5} 五位数字           10001（前六位省市县地区）
    //(18|19|20)                19（现阶段可能取值范围18xx-20xx年）
    //\\d{2}                    91（年份）
    //((0[1-9])|(10|11|12))     01（月份）
    //(([0-2][1-9])|10|20|30|31)01（日期）
    //\\d{3} 三位数字            123（第十七位奇数代表男，偶数代表女）
    //[0-9Xx] 0123456789Xx其中的一个 X（第十八位为校验值）
    //$结尾

    //假设15位身份证号码:410001910101123  410001 910101 123
    //^开头
    //[1-9] 第一位1-9中的一个      4
    //\\d{5} 五位数字           10001（前六位省市县地区）
    //\\d{2}                    91（年份）
    //((0[1-9])|(10|11|12))     01（月份）
    //(([0-2][1-9])|10|20|30|31)01（日期）
    //\\d{3} 三位数字            123（第十五位奇数代表男，偶数代表女），15位身份证不含X
    //$结尾


    val matches = IDNumber.matches(regularExpression.toRegex())

    //判断第18位校验值
    if (matches) {

        if (IDNumber.length == 18) {
            try {
                val charArray = IDNumber.toCharArray()
                //前十七位加权因子
                val idCardWi = intArrayOf(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
                //这是除以11后，可能产生的11位余数对应的验证码
                val idCardY = arrayOf("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2")
                var sum = 0
                for (i in idCardWi.indices) {
                    val current = Integer.parseInt(charArray[i].toString())
                    val count = current * idCardWi[i]
                    sum += count
                }
                val idCardLast = charArray[17]
                val idCardMod = sum % 11
                if (idCardY[idCardMod].toUpperCase() == idCardLast.toString().toUpperCase()) {
                    return true
                } else {
                    println(
                        "身份证最后一位:" + idCardLast.toString().toUpperCase() +
                                "错误,正确的应该是:" + idCardY[idCardMod].toUpperCase()
                    )
                    return false
                }

            } catch (e: Exception) {
                e.printStackTrace()
                println("异常:$IDNumber")
                return false
            }

        }

    }
    return matches
}

/**
 * 判断是否含有特殊字符
 *
 * @param str
 * @return true为包含，false为不包含
 */
fun isSpecialChar(str: String): Boolean {
    val regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\n|\r|\t"
    val p = Pattern.compile(regEx)
    val m = p.matcher(str)
    return m.find()
}

/**
 * 判断字符串是否全部为中文字符组成
 * @param str    检测的文字
 * @return    true：为中文字符串，false:含有非中文字符
 */
fun isChineseStr(str: String): Boolean {
    val pattern = Pattern.compile("[\u4e00-\u9fa5]")
    val c = str.toCharArray()
    for (i in c.indices) {
        val matcher = pattern.matcher(c[i].toString())
        if (!matcher.matches()) {
            return false
        }
    }
    return true
}

@SuppressLint("SimpleDateFormat")
fun compareTwoTime(starTime: String?, endString: String?): Boolean {
    loge("starTime: $starTime endString: $endString")
    var isDayu = false
    val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")
    try {
        val parse = dateFormat.parse(starTime)
        val parse1 = dateFormat.parse(endString)
        val diff = parse1.time - parse.time
        isDayu = diff > 0
    } catch (e: ParseException) {
        e.printStackTrace()
    }
    return isDayu
}

//fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
//    val loggingInterceptor = HttpLoggingInterceptor()
//    loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
//    return loggingInterceptor
//}

// 将数字转换成字母
fun numToLetter(index: Int) = when (index) {
    0 -> "A"
    1 -> "B"
    2 -> "C"
    else -> "D"
}

fun getFontSize(level: Int) = when (level) {
    1 -> 13
    2 -> 15
    3 -> 17
    4 -> 19
    5 -> 21
    else -> 23
}

private const val MIN_DELAY_TIME = 2000 // 两次点击间隔不能少于1000ms

private var lastClickTime: Long = 0

fun isFastClick(): Boolean {
    var flag = true
    val currentClickTime = System.currentTimeMillis()
    if (currentClickTime - lastClickTime >= MIN_DELAY_TIME) {
        flag = false
    }
    lastClickTime = currentClickTime
    return flag
}

fun filterEmoji(source: String?): String? {
    var source = source
    if (source != null) {
        val emoji: Pattern = Pattern.compile(
            "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]",
            Pattern.UNICODE_CASE or Pattern.CASE_INSENSITIVE
        )
        val emojiMatcher: Matcher = emoji.matcher(source)
        if (emojiMatcher.find()) {
            source = emojiMatcher.replaceAll("")
            return source
        }
        return source
    }
    return source

}

fun getHttpLoggingInterceptor(): HttpLoggingInterceptor {
    val loggingInterceptor = HttpLoggingInterceptor()
    loggingInterceptor.level = HttpLoggingInterceptor.Level.BASIC
    return loggingInterceptor
}

fun toRequestBody(any: Any): RequestBody {
    val json = toJson(any)
    Log.e("jsonParams",json.toString())
    return json.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
}

fun getLocalIPv4Address(): String? {
    try {
        val interfaces = Collections.list(NetworkInterface.getNetworkInterfaces())
        for (intf in interfaces) {
            for (addr in Collections.list(intf.inetAddresses)) {
                if (!addr.isLoopbackAddress && addr is Inet4Address) {
                    return addr.hostAddress
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return null
}

//object VideoThumbnailLoader {
    // 使用协程实现异步（推荐）
    suspend fun loadThumbnail(context: Context, videoUri: String, width: Int, height: Int, imageView:ImageView): Bitmap? =
        withContext(Dispatchers.IO) { // 切换到 IO 线程
            val retriever = MediaMetadataRetriever()
            try {
                retriever.setDataSource(/*context,*/ videoUri)
                // 提取第1秒的帧（单位：微秒）
                val frame = retriever.getFrameAtTime(1_000_000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC)
                // 显示在ImageView上
//                imageView.setImageBitmap(frame)
                frame?.let { Bitmap.createScaledBitmap(it, width, height, true) }
            } catch (e: Exception) {
                null
            } finally {
                retriever.release()
            }
        }


/**
 * 跳转到应用商店（优先跳转对应品牌商店，否则跳转 Google Play 或浏览器）
 * @param context 上下文
 * @param packageName 目标应用的包名（默认当前应用）
 */
fun jumpToAppStore(context: Context, packageName: String = context.packageName) {
    // 品牌与商店包名、URI 的映射表（可扩展）
    val storeMap = mapOf(
        "huawei" to StoreInfo(
            packageName = "com.huawei.appmarket",
            marketUri = "market://details?id=$packageName",
            webUrl = "https://appgallery.huawei.com/app/$packageName"
        ),
        "xiaomi" to StoreInfo(
            packageName = "com.xiaomi.market",
            marketUri = "market://details?id=$packageName",
            webUrl = "http://app.mi.com/detail/$packageName"
        ),
        "oppo" to StoreInfo(
            packageName = "com.oppo.market",
            marketUri = "oppomarket://details?packagename=$packageName",
            webUrl = "https://heytap.com/appdetail/app/$packageName"
        ),
        "vivo" to StoreInfo(
            packageName = "com.vivo.appstore",
            marketUri = "vivomarket://details?id=$packageName",
            webUrl = "https://api.vip.vivo.com.cn/app/info/$packageName"
        ),
        "samsung" to StoreInfo(
            packageName = "com.sec.android.app.samsungapps",
            marketUri = "samsungapps://ProductDetail/$packageName",
            webUrl = "https://galaxystore.samsung.com/detail/$packageName"
        ),
        "honor" to StoreInfo(  // 新增荣耀
            packageName = "com.hihonor.appmarket",
            marketUri = "honormarket://details?id=$packageName",
            webUrl = "https://appgallery.hihonor.com/app/$packageName"
        ),
        "realme" to StoreInfo( // 新增 Realme
            packageName = "com.heytap.market",
            marketUri = "heytapmarket://details?id=$packageName",
            webUrl = "https://heytap.com/appdetail/app/$packageName"
        )
    )

    // 获取设备品牌（兼容处理为小写）
    val brand = Build.MANUFACTURER.lowercase()

    // 匹配品牌对应的商店信息
    val (targetPackage, targetUri, webUrl) = storeMap[brand]?.let {
        Triple(it.packageName, it.marketUri, it.webUrl)
    } ?: run {
        // 默认使用 Google Play
        Triple(
            "com.android.vending",
            "market://details?id=$packageName",
            "https://play.google.com/store/apps/details?id=$packageName"
        )
    }

    try {
        // 优先检查目标商店是否已安装
        if (isPackageInstalled(context, targetPackage)) {
            val intent = Intent(Intent.ACTION_VIEW).apply {
                data = Uri.parse(targetUri)
                setPackage(targetPackage) // 强制指定商店包名
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            context.startActivity(intent)
        } else {
            // 未安装商店则打开浏览器
            openWebBrowser(context, webUrl)
        }
    } catch (e: Exception) {
        // 异常时跳转浏览器
        openWebBrowser(context, webUrl)
    }
}

/**
 * 检查是否已安装指定包名的应用
 */
private fun isPackageInstalled(context: Context, packageName: String): Boolean {
    return try {
        context.packageManager.getPackageInfo(packageName, 0)
        true
    } catch (e: PackageManager.NameNotFoundException) {
        false
    }
}

/**
 * 打开浏览器访问 URL
 */
private fun openWebBrowser(context: Context, url: String) {
    try {
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }
        context.startActivity(intent)
    } catch (e: Exception) {
        Toast.makeText(context, "无法跳转到应用商店", Toast.LENGTH_SHORT).show()
    }
}

// 商店信息数据类
data class StoreInfo(
    val packageName: String,
    val marketUri: String,
    val webUrl: String
)

@SuppressLint("NewApi")
fun loadVideoThumbnail(context: Context, videoPath: String, imageView: ImageView) {
    val mediaMetadataRetriever = MediaMetadataRetriever()
    try {
        mediaMetadataRetriever.setDataSource(videoPath)

        // 获取原始宽高和旋转角度
        val width = mediaMetadataRetriever.extractMetadata(METADATA_KEY_VIDEO_WIDTH)?.toInt() ?: 0
        val height = mediaMetadataRetriever.extractMetadata(METADATA_KEY_VIDEO_HEIGHT)?.toInt() ?: 0
        val rotation = mediaMetadataRetriever.extractMetadata(METADATA_KEY_VIDEO_ROTATION)?.toInt() ?: 0

        // 计算实际宽高（考虑旋转）
        val (originalWidth, originalHeight) = if (rotation == 90 || rotation == 270) height to width else width to height

        // 根据 ImageView 尺寸计算目标宽高
        val imageViewWidth = imageView.width.takeIf { it > 0 } ?: originalWidth
        val imageViewHeight = imageView.height.takeIf { it > 0 } ?: originalHeight
        val targetWidth = imageViewWidth
        val targetHeight = (originalHeight * (targetWidth.toFloat() / originalWidth)).toInt()

        // 生成缩略图
        val bitmap = mediaMetadataRetriever.getScaledFrameAtTime(
            0,
            MediaMetadataRetriever.OPTION_CLOSEST,
            targetWidth,
            targetHeight
        )?.let { rawBitmap ->
            if (rotation != 0) adjustBitmapRotation(rawBitmap, rotation) else rawBitmap
        }

        // 显示到 ImageView
        bitmap?.let {
            imageView.post {
                imageView.setImageBitmap(it)
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        mediaMetadataRetriever.release()
    }
}

private fun adjustBitmapRotation(bitmap: Bitmap, rotation: Int): Bitmap {
    val matrix = Matrix().apply { postRotate(rotation.toFloat()) }
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}

fun formatPrice(price: Double): String {
    val decimalFormat = DecimalFormat("#.##") // 最多保留两位小数，自动去零
    return decimalFormat.format(price)
}

fun Context.loading(show: Boolean) {
    if (show) MProgressDialog.showProgress(this) else MProgressDialog.dismissProgress()
}

fun Context.loading(show: Boolean, msg: String) {
    if (show) MProgressDialog.showProgress(this, msg) else MProgressDialog.dismissProgress()
}